{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Quick Start"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `ssms` package serves two purposes. \n",
    "\n",
    "1. Easy access to *fast simulators of sequential sampling models*\n",
    "   \n",
    "2. Support infrastructure to construct training data for various approaches to likelihood / posterior amortization\n",
    "\n",
    "We provide two minimal examples here to illustrate how to use each of the two capabilities.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Install \n",
    "\n",
    "Let's start with *installing* the `ssms` package.\n",
    "\n",
    "You can do so by typing,\n",
    "\n",
    "`pip install git+https://github.com/AlexanderFengler/ssm_simulators`\n",
    "\n",
    "in your terminal.\n",
    "\n",
    "Below you find a basic tutorial on how to use the package."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Tutorial"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Import necessary packages\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import ssms"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Using the Simulators\n",
    "\n",
    "Let's start with using the basic simulators. \n",
    "You access the main simulators through the  `ssms.basic_simulators.simulator` function.\n",
    "\n",
    "To get an idea about the models included in `ssms`, use the `config` module.\n",
    "The central dictionary with metadata about included models sits in `ssms.config.model_config`. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['ddm',\n",
       " 'ddm_legacy',\n",
       " 'ddm_deadline',\n",
       " 'angle',\n",
       " 'weibull',\n",
       " 'levy',\n",
       " 'levy_angle',\n",
       " 'full_ddm',\n",
       " 'gamma_drift',\n",
       " 'gamma_drift_angle',\n",
       " 'ds_conflict_drift',\n",
       " 'ds_conflict_drift_angle',\n",
       " 'ornstein',\n",
       " 'ornstein_angle',\n",
       " 'ddm_sdv',\n",
       " 'race_2',\n",
       " 'race_no_bias_2',\n",
       " 'race_no_z_2',\n",
       " 'race_no_bias_angle_2',\n",
       " 'race_no_z_angle_2',\n",
       " 'race_3',\n",
       " 'race_no_bias_3',\n",
       " 'race_no_z_3',\n",
       " 'race_no_bias_angle_3',\n",
       " 'race_no_z_angle_3',\n",
       " 'race_4',\n",
       " 'race_no_bias_4',\n",
       " 'race_no_z_4',\n",
       " 'race_no_bias_angle_4',\n",
       " 'race_no_z_angle_4',\n",
       " 'lca_3',\n",
       " 'lca_no_bias_3',\n",
       " 'lca_no_z_3',\n",
       " 'lca_no_bias_angle_3',\n",
       " 'lca_no_z_angle_3',\n",
       " 'lca_4',\n",
       " 'lca_no_bias_4',\n",
       " 'lca_no_z_4',\n",
       " 'lca_no_bias_angle_4',\n",
       " 'lca_no_z_angle_4',\n",
       " 'ddm_par2',\n",
       " 'ddm_par2_no_bias',\n",
       " 'ddm_par2_conflict_gamma_no_bias',\n",
       " 'ddm_par2_angle_no_bias',\n",
       " 'ddm_par2_weibull_no_bias',\n",
       " 'ddm_seq2',\n",
       " 'ddm_seq2_no_bias',\n",
       " 'ddm_seq2_conflict_gamma_no_bias',\n",
       " 'ddm_seq2_angle_no_bias',\n",
       " 'ddm_seq2_weibull_no_bias',\n",
       " 'ddm_mic2_adj',\n",
       " 'ddm_mic2_adj_no_bias',\n",
       " 'ddm_mic2_adj_conflict_gamma_no_bias',\n",
       " 'ddm_mic2_adj_angle_no_bias',\n",
       " 'ddm_mic2_adj_weibull_no_bias',\n",
       " 'ddm_mic2_ornstein',\n",
       " 'ddm_mic2_ornstein_no_bias',\n",
       " 'ddm_mic2_ornstein_conflict_gamma_no_bias',\n",
       " 'ddm_mic2_ornstein_angle_no_bias',\n",
       " 'ddm_mic2_ornstein_weibull_no_bias',\n",
       " 'ddm_mic2_leak',\n",
       " 'ddm_mic2_leak_no_bias',\n",
       " 'ddm_mic2_leak_conflict_gamma_no_bias',\n",
       " 'ddm_mic2_leak_angle_no_bias',\n",
       " 'ddm_mic2_leak_weibull_no_bias',\n",
       " 'tradeoff_no_bias',\n",
       " 'tradeoff_angle_no_bias',\n",
       " 'tradeoff_weibull_no_bias',\n",
       " 'tradeoff_conflict_gamma_no_bias',\n",
       " 'glob',\n",
       " 'weibull_cdf',\n",
       " 'full_ddm2']"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Check included models\n",
    "list(ssms.config.model_config.keys())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'name': 'ddm_deadline',\n",
       " 'params': ['v', 'a', 'z', 't', 'deadline'],\n",
       " 'param_bounds': [[-3.0, 0.3, 0.1, 0.0, 0.1], [3.0, 2.5, 0.9, 2.0, 5.0]],\n",
       " 'boundary': <function ssms.basic_simulators.boundary_functions.constant(t=0)>,\n",
       " 'n_params': 5,\n",
       " 'default_params': [0.0, 1.0, 0.5, 0.001, 5.0],\n",
       " 'hddm_include': ['z', 'deadline'],\n",
       " 'nchoices': 2}"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ssms.config.model_config[\"ddm_deadline\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'name': 'ddm',\n",
       " 'params': ['v', 'a', 'z', 't'],\n",
       " 'param_bounds': [[-3.0, 0.3, 0.1, 0.0], [3.0, 2.5, 0.9, 2.0]],\n",
       " 'boundary': <function ssms.basic_simulators.boundary_functions.constant(t=0)>,\n",
       " 'n_params': 4,\n",
       " 'default_params': [0.0, 1.0, 0.5, 0.001],\n",
       " 'hddm_include': ['z'],\n",
       " 'nchoices': 2}"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Take an example config for a given model\n",
    "ssms.config.model_config[\"ddm\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Note:**\n",
    "The usual structure of these models includes,\n",
    "\n",
    "- Parameter names (`'params'`)\n",
    "- Bounds on the parameters (`'param_bounds'`)\n",
    "- A function that defines a boundary for the respective model (`'boundary'`)\n",
    "- The number of parameters (`'n_params'`)\n",
    "- Defaults for the parameters (`'default_params'`)\n",
    "- The number of choices the process can produce (`'nchoices'`)\n",
    "\n",
    "The `'hddm_include'` key concerns information useful for integration with the [hddm](https://github.com/hddm-devs/hddm) python package, which facilitates hierarchical bayesian inference for sequential sampling models. It is not important for the present tutorial."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "from ssms.basic_simulators.simulator import simulator\n",
    "\n",
    "p_choice_vec = []\n",
    "dline_tmp_vec = []\n",
    "for dline_tmp in np.linspace(0.2, 5, 20):\n",
    "    sim_out = simulator(\n",
    "        model=\"ddm_deadline\", theta=[1.0, 1.0, 0.5, 0.5, dline_tmp], n_samples=10000\n",
    "    )\n",
    "    p_choice_vec.append(np.sum(sim_out[\"choices\"] == 1.0) / sim_out[\"choices\"].shape[0])\n",
    "    dline_tmp_vec.append(dline_tmp)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x16fcd03a0>]"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from matplotlib import pyplot as plt\n",
    "\n",
    "plt.plot(dline_tmp_vec, p_choice_vec)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([   2.,    0.,    2.,    2.,    4.,    4.,    2.,    5.,    7.,\n",
       "           5.,   15.,   15.,   26.,   50.,   52.,   62.,  111.,  116.,\n",
       "         195.,  221.,  234.,   45.,    0.,    0.,    0.,    0.,    0.,\n",
       "         263., 1796., 1810., 1326.,  930.,  759.,  517.,  400.,  266.,\n",
       "         205.,  154.,  104.,   74.,   60.,   40.,   24.,   29.,   17.,\n",
       "          15.,   15.,    8.,    3.,    7.]),\n",
       " array([-4.67442942, -4.4839405 , -4.29345158, -4.10296266, -3.91247374,\n",
       "        -3.72198482, -3.5314959 , -3.34100698, -3.15051805, -2.96002913,\n",
       "        -2.76954021, -2.57905129, -2.38856237, -2.19807345, -2.00758453,\n",
       "        -1.81709561, -1.62660669, -1.43611777, -1.24562885, -1.05513993,\n",
       "        -0.86465101, -0.67416209, -0.48367317, -0.29318425, -0.10269533,\n",
       "         0.08779359,  0.27828251,  0.46877143,  0.65926035,  0.84974927,\n",
       "         1.04023819,  1.23072711,  1.42121603,  1.61170495,  1.80219387,\n",
       "         1.99268279,  2.18317171,  2.37366063,  2.56414955,  2.75463847,\n",
       "         2.94512739,  3.13561631,  3.32610523,  3.51659415,  3.70708307,\n",
       "         3.89757199,  4.08806091,  4.27854983,  4.46903875,  4.65952767,\n",
       "         4.85001659]),\n",
       " <BarContainer object of 50 artists>)"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from matplotlib import pyplot as plt\n",
    "\n",
    "plt.hist(\n",
    "    sim_out[\"rts\"][sim_out[\"rts\"] != -999] * sim_out[\"choices\"][sim_out[\"rts\"] != -999],\n",
    "    bins=50,\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1.26040506,  1.        ],\n",
       "       [ 1.56888986, -1.        ],\n",
       "       [ 1.09187531, -1.        ],\n",
       "       ...,\n",
       "       [ 0.75505078, -1.        ],\n",
       "       [ 0.89852297,  1.        ],\n",
       "       [ 1.17158473, -1.        ]])"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.hstack([sim_out[\"rts\"], sim_out[\"choices\"]])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The output of the simulator is a `dictionary` with three elements.\n",
    "\n",
    "1. `rts` (array)\n",
    "2. `choices` (array)\n",
    "3. `metadata` (dictionary)\n",
    "\n",
    "The `metadata` includes the named parameters, simulator settings, and more."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Using the Training Data Generators\n",
    "\n",
    "The training data generators sit on top of the simulator function to turn raw simulations into usable training data for training machine learning algorithms aimed at posterior or likelihood armortization.\n",
    "\n",
    "We will use the `data_generator` class from `ssms.dataset_generators`. Initializing the `data_generator` boils down to supplying two configuration dictionaries.\n",
    "\n",
    "1. The `generator_config`, concerns choices as to what kind of training data one wants to generate.\n",
    "2. The `model_config` concerns choices with respect to the underlying generative *sequential sampling model*. \n",
    "\n",
    "We will consider a basic example here, concerning data generation to prepare for training [LANs](https://elifesciences.org/articles/65074).\n",
    "\n",
    "Let's start by peeking at an example `generator_config`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'output_folder': 'data/lan_mlp/',\n",
       " 'dgp_list': 'ddm',\n",
       " 'nbins': 0,\n",
       " 'n_samples': 100000,\n",
       " 'n_parameter_sets': 10000,\n",
       " 'n_parameter_sets_rejected': 100,\n",
       " 'n_training_samples_by_parameter_set': 1000,\n",
       " 'max_t': 20.0,\n",
       " 'delta_t': 0.001,\n",
       " 'pickleprotocol': 4,\n",
       " 'n_cpus': 'all',\n",
       " 'kde_data_mixture_probabilities': [0.8, 0.1, 0.1],\n",
       " 'simulation_filters': {'mode': 20,\n",
       "  'choice_cnt': 0,\n",
       "  'mean_rt': 17,\n",
       "  'std': 0,\n",
       "  'mode_cnt_rel': 0.95},\n",
       " 'negative_rt_cutoff': -66.77497,\n",
       " 'n_subruns': 10,\n",
       " 'bin_pointwise': False,\n",
       " 'separate_response_channels': False}"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ssms.config.data_generator_config[\"lan\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You usually have to make just few changes to this basic configuration dictionary.\n",
    "An example below."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "from copy import deepcopy\n",
    "\n",
    "# Initialize the generator config (for MLP LANs)\n",
    "generator_config = deepcopy(ssms.config.data_generator_config[\"snpe\"])\n",
    "# Specify generative model (one from the list of included models mentioned above)\n",
    "generator_config[\"dgp_list\"] = \"angle\"\n",
    "# Specify number of parameter sets to simulate\n",
    "generator_config[\"n_parameter_sets\"] = 100\n",
    "# Specify how many samples a simulation run should entail\n",
    "generator_config[\"n_samples\"] = 1000"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now let's define our corresponding `model_config`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'name': 'angle', 'params': ['v', 'a', 'z', 't', 'theta'], 'param_bounds': [[-3.0, 0.3, 0.1, 0.001, -0.1], [3.0, 3.0, 0.9, 2.0, 1.3]], 'boundary': <function angle at 0x11bd60b80>, 'n_params': 5, 'default_params': [0.0, 1.0, 0.5, 0.001, 0.0], 'hddm_include': ['z', 'theta'], 'nchoices': 2}\n"
     ]
    }
   ],
   "source": [
    "model_config = ssms.config.model_config[\"angle\"]\n",
    "print(model_config)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We are now ready to initialize a `data_generator`, after which we can generate training data using the `generate_data_training_uniform` function, which will use the hypercube defined by our parameter bounds from the `model_config` to uniformly generate parameter sets and corresponding simulated datasets."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "n_cpus used:  6\n",
      "checking:  data/snpe_training/\n"
     ]
    }
   ],
   "source": [
    "my_dataset_generator = ssms.dataset_generators.data_generator_snpe(\n",
    "    generator_config=generator_config, model_config=model_config\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "simulation round: 1  of 10\n",
      "simulation round: 2  of 10\n",
      "simulation round: 3  of 10\n",
      "simulation round: 4  of 10\n",
      "simulation round: 5  of 10\n",
      "simulation round: 6  of 10\n",
      "simulation round: 7  of 10\n",
      "simulation round: 8  of 10\n",
      "simulation round: 9  of 10\n",
      "simulation round: 10  of 10\n",
      "Writing to file:  data/snpe_training/training_data__n_1000/angle/training_data_angle_4c70e020dace11ec9074acde48001122.pickle\n"
     ]
    }
   ],
   "source": [
    "training_data = my_dataset_generator.generate_data_training_uniform(save=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "new_features = {\n",
    "    i: {\n",
    "        \"data\": training_data[0][i][\"features\"],\n",
    "        \"labels\": training_data[0][i][\"labels\"],\n",
    "    }\n",
    "    for i in range(len(training_data[0]))\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dict_keys([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99])"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "training_data.keys()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "trainin"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'features: ': array([[ 4.10223436,  1.        ],\n",
       "         [ 2.655339  ,  1.        ],\n",
       "         [ 3.40328479,  1.        ],\n",
       "         ...,\n",
       "         [ 2.71133494,  1.        ],\n",
       "         [ 0.60232329, -1.        ],\n",
       "         [ 1.18331599, -1.        ]]),\n",
       "  'labels': array([ 1.2677877 ,  2.0692544 ,  0.17184597,  0.36032298, -0.06370651],\n",
       "        dtype=float32),\n",
       "  'meta': {'v': array([1.2677877], dtype=float32),\n",
       "   'a': array([2.0692544], dtype=float32),\n",
       "   'z': array([0.17184597], dtype=float32),\n",
       "   't': array([0.36032298], dtype=float32),\n",
       "   's': 1.0,\n",
       "   'theta': array([-0.06370651], dtype=float32),\n",
       "   'delta_t': 0.0010000000474974513,\n",
       "   'max_t': 20.0,\n",
       "   'n_samples': 1000,\n",
       "   'simulator': 'ddm_flexbound',\n",
       "   'boundary_fun_type': 'angle',\n",
       "   'possible_choices': [-1, 1],\n",
       "   'trajectory': array([[  -1.3580683],\n",
       "          [  -1.3061538],\n",
       "          [  -1.3130792],\n",
       "          ...,\n",
       "          [-999.       ],\n",
       "          [-999.       ],\n",
       "          [-999.       ]], dtype=float32),\n",
       "   'boundary': array([2.0692544, 2.0693183, 2.069382 , ..., 3.3449836, 3.3450472,\n",
       "          3.345111 ], dtype=float32),\n",
       "   'model': 'angle'}},\n",
       " {'features: ': array([[1.02261758, 1.        ],\n",
       "         [1.04661727, 1.        ],\n",
       "         [1.06361699, 1.        ],\n",
       "         ...,\n",
       "         [0.93361747, 1.        ],\n",
       "         [1.46661186, 1.        ],\n",
       "         [1.03261745, 1.        ]]),\n",
       "  'labels': array([2.604681 , 1.3304262, 0.5099575, 0.7646173, 0.8860518],\n",
       "        dtype=float32),\n",
       "  'meta': {'v': array([2.604681], dtype=float32),\n",
       "   'a': array([1.3304262], dtype=float32),\n",
       "   'z': array([0.5099575], dtype=float32),\n",
       "   't': array([0.7646173], dtype=float32),\n",
       "   's': 1.0,\n",
       "   'theta': array([0.8860518], dtype=float32),\n",
       "   'delta_t': 0.0010000000474974513,\n",
       "   'max_t': 20.0,\n",
       "   'n_samples': 1000,\n",
       "   'simulator': 'ddm_flexbound',\n",
       "   'boundary_fun_type': 'angle',\n",
       "   'possible_choices': [-1, 1],\n",
       "   'trajectory': array([[ 2.6495418e-02],\n",
       "          [ 7.9746895e-02],\n",
       "          [ 7.4158326e-02],\n",
       "          ...,\n",
       "          [-9.9900000e+02],\n",
       "          [-9.9900000e+02],\n",
       "          [-9.9900000e+02]], dtype=float32),\n",
       "   'boundary': array([  1.3304262,   1.3292016,   1.3279768, ..., -23.160759 ,\n",
       "          -23.161983 , -23.163208 ], dtype=float32),\n",
       "   'model': 'angle'}},\n",
       " {'features: ': array([[ 0.96705407,  1.        ],\n",
       "         [ 0.935054  ,  1.        ],\n",
       "         [ 0.87205386, -1.        ],\n",
       "         ...,\n",
       "         [ 0.90805393,  1.        ],\n",
       "         [ 0.96405405,  1.        ],\n",
       "         [ 1.02105391,  1.        ]]),\n",
       "  'labels': array([1.2017035 , 0.97606236, 0.39102793, 0.7560538 , 1.2579942 ],\n",
       "        dtype=float32),\n",
       "  'meta': {'v': array([1.2017035], dtype=float32),\n",
       "   'a': array([0.97606236], dtype=float32),\n",
       "   'z': array([0.39102793], dtype=float32),\n",
       "   't': array([0.7560538], dtype=float32),\n",
       "   's': 1.0,\n",
       "   'theta': array([1.2579942], dtype=float32),\n",
       "   'delta_t': 0.0010000000474974513,\n",
       "   'max_t': 20.0,\n",
       "   'n_samples': 1000,\n",
       "   'simulator': 'ddm_flexbound',\n",
       "   'boundary_fun_type': 'angle',\n",
       "   'possible_choices': [-1, 1],\n",
       "   'trajectory': array([[-2.1272707e-01],\n",
       "          [-1.6087857e-01],\n",
       "          [-1.6787012e-01],\n",
       "          ...,\n",
       "          [-9.9900000e+02],\n",
       "          [-9.9900000e+02],\n",
       "          [-9.9900000e+02]], dtype=float32),\n",
       "   'boundary': array([  0.97606236,   0.9729704 ,   0.96987844, ..., -60.856857  ,\n",
       "          -60.859947  , -60.863037  ], dtype=float32),\n",
       "   'model': 'angle'}},\n",
       " {'features: ': array([[ 1.00975132, -1.        ],\n",
       "         [ 1.27174985, -1.        ],\n",
       "         [ 1.12875164, -1.        ],\n",
       "         ...,\n",
       "         [ 0.99275136, -1.        ],\n",
       "         [ 1.25475013, -1.        ],\n",
       "         [ 1.45274758, -1.        ]]),\n",
       "  'labels': array([-1.6534374 ,  1.5941297 ,  0.12224997,  0.8867513 ,  0.23367152],\n",
       "        dtype=float32),\n",
       "  'meta': {'v': array([-1.6534374], dtype=float32),\n",
       "   'a': array([1.5941297], dtype=float32),\n",
       "   'z': array([0.12224997], dtype=float32),\n",
       "   't': array([0.8867513], dtype=float32),\n",
       "   's': 1.0,\n",
       "   'theta': array([0.23367152], dtype=float32),\n",
       "   'delta_t': 0.0010000000474974513,\n",
       "   'max_t': 20.0,\n",
       "   'n_samples': 1000,\n",
       "   'simulator': 'ddm_flexbound',\n",
       "   'boundary_fun_type': 'angle',\n",
       "   'possible_choices': [-1, 1],\n",
       "   'trajectory': array([[  -1.2043651],\n",
       "          [  -1.1553718],\n",
       "          [  -1.1652185],\n",
       "          ...,\n",
       "          [-999.       ],\n",
       "          [-999.       ],\n",
       "          [-999.       ]], dtype=float32),\n",
       "   'boundary': array([ 1.5941297,  1.5938916,  1.5936537, ..., -3.1657853, -3.1660233,\n",
       "          -3.1662607], dtype=float32),\n",
       "   'model': 'angle'}},\n",
       " {'features: ': array([[ 1.26257348, -1.        ],\n",
       "         [ 0.6515795 ,  1.        ],\n",
       "         [ 0.95757735, -1.        ],\n",
       "         ...,\n",
       "         [ 0.97157717, -1.        ],\n",
       "         [ 0.83357894,  1.        ],\n",
       "         [ 0.77157974, -1.        ]]),\n",
       "  'labels': array([-1.4438915 ,  0.9805305 ,  0.69183505,  0.5205794 ,  0.6480955 ],\n",
       "        dtype=float32),\n",
       "  'meta': {'v': array([-1.4438915], dtype=float32),\n",
       "   'a': array([0.9805305], dtype=float32),\n",
       "   'z': array([0.69183505], dtype=float32),\n",
       "   't': array([0.5205794], dtype=float32),\n",
       "   's': 1.0,\n",
       "   'theta': array([0.6480955], dtype=float32),\n",
       "   'delta_t': 0.0010000000474974513,\n",
       "   'max_t': 20.0,\n",
       "   'n_samples': 1000,\n",
       "   'simulator': 'ddm_flexbound',\n",
       "   'boundary_fun_type': 'angle',\n",
       "   'possible_choices': [-1, 1],\n",
       "   'trajectory': array([[ 3.7620023e-01],\n",
       "          [ 4.2540312e-01],\n",
       "          [ 4.1576597e-01],\n",
       "          ...,\n",
       "          [-9.9900000e+02],\n",
       "          [-9.9900000e+02],\n",
       "          [-9.9900000e+02]], dtype=float32),\n",
       "   'boundary': array([  0.9805305 ,   0.9797733 ,   0.97901607, ..., -14.162027  ,\n",
       "          -14.162784  , -14.163541  ], dtype=float32),\n",
       "   'model': 'angle'}},\n",
       " {'features: ': array([[0.91735744, 1.        ],\n",
       "         [1.20835662, 1.        ],\n",
       "         [0.92935741, 1.        ],\n",
       "         ...,\n",
       "         [0.90235746, 1.        ],\n",
       "         [0.89735746, 1.        ],\n",
       "         [1.31435525, 1.        ]]),\n",
       "  'labels': array([1.9964801, 1.4816018, 0.8841693, 0.8633575, 1.0173286],\n",
       "        dtype=float32),\n",
       "  'meta': {'v': array([1.9964801], dtype=float32),\n",
       "   'a': array([1.4816018], dtype=float32),\n",
       "   'z': array([0.8841693], dtype=float32),\n",
       "   't': array([0.8633575], dtype=float32),\n",
       "   's': 1.0,\n",
       "   'theta': array([1.0173286], dtype=float32),\n",
       "   'delta_t': 0.0010000000474974513,\n",
       "   'max_t': 20.0,\n",
       "   'n_samples': 1000,\n",
       "   'simulator': 'ddm_flexbound',\n",
       "   'boundary_fun_type': 'angle',\n",
       "   'possible_choices': [-1, 1],\n",
       "   'trajectory': array([[   1.1383718],\n",
       "          [   1.0790156],\n",
       "          [   1.0546436],\n",
       "          ...,\n",
       "          [-999.       ],\n",
       "          [-999.       ],\n",
       "          [-999.       ]], dtype=float32),\n",
       "   'boundary': array([  1.4816018,   1.4799834,   1.478365 , ..., -30.883564 ,\n",
       "          -30.885181 , -30.886799 ], dtype=float32),\n",
       "   'model': 'angle'}},\n",
       " {'features: ': array([[ 2.23801517, -1.        ],\n",
       "         [ 1.17800593,  1.        ],\n",
       "         [ 3.20701861, -1.        ],\n",
       "         ...,\n",
       "         [ 1.28100467,  1.        ],\n",
       "         [ 2.52602863, -1.        ],\n",
       "         [ 3.33400941, -1.        ]]),\n",
       "  'labels': array([-1.3583255 ,  1.9194802 ,  0.76933956,  0.85600656,  0.14019692],\n",
       "        dtype=float32),\n",
       "  'meta': {'v': array([-1.3583255], dtype=float32),\n",
       "   'a': array([1.9194802], dtype=float32),\n",
       "   'z': array([0.76933956], dtype=float32),\n",
       "   't': array([0.85600656], dtype=float32),\n",
       "   's': 1.0,\n",
       "   'theta': array([0.14019692], dtype=float32),\n",
       "   'delta_t': 0.0010000000474974513,\n",
       "   'max_t': 20.0,\n",
       "   'n_samples': 1000,\n",
       "   'simulator': 'ddm_flexbound',\n",
       "   'boundary_fun_type': 'angle',\n",
       "   'possible_choices': [-1, 1],\n",
       "   'trajectory': array([[ 1.0339839e+00],\n",
       "          [ 1.0211202e+00],\n",
       "          [ 9.7800064e-01],\n",
       "          ...,\n",
       "          [-9.9900000e+02],\n",
       "          [-9.9900000e+02],\n",
       "          [-9.9900000e+02]], dtype=float32),\n",
       "   'boundary': array([ 1.9194802 ,  1.9193391 ,  1.9191979 , ..., -0.9026922 ,\n",
       "          -0.90283334, -0.90297425], dtype=float32),\n",
       "   'model': 'angle'}},\n",
       " {'features: ': array([[1.76377082, 1.        ],\n",
       "         [1.77377069, 1.        ],\n",
       "         [1.61377048, 1.        ],\n",
       "         ...,\n",
       "         [1.95776832, 1.        ],\n",
       "         [1.74777079, 1.        ],\n",
       "         [1.8307699 , 1.        ]]),\n",
       "  'labels': array([1.3629639, 1.579064 , 0.8027136, 1.5157704, 1.1332113],\n",
       "        dtype=float32),\n",
       "  'meta': {'v': array([1.3629639], dtype=float32),\n",
       "   'a': array([1.579064], dtype=float32),\n",
       "   'z': array([0.8027136], dtype=float32),\n",
       "   't': array([1.5157704], dtype=float32),\n",
       "   's': 1.0,\n",
       "   'theta': array([1.1332113], dtype=float32),\n",
       "   'delta_t': 0.0010000000474974513,\n",
       "   'max_t': 20.0,\n",
       "   'n_samples': 1000,\n",
       "   'simulator': 'ddm_flexbound',\n",
       "   'boundary_fun_type': 'angle',\n",
       "   'possible_choices': [-1, 1],\n",
       "   'trajectory': array([[ 9.5600820e-01],\n",
       "          [ 9.7418803e-01],\n",
       "          [ 9.7369546e-01],\n",
       "          ...,\n",
       "          [-9.9900000e+02],\n",
       "          [-9.9900000e+02],\n",
       "          [-9.9900000e+02]], dtype=float32),\n",
       "   'boundary': array([  1.579064 ,   1.5769265,   1.574789 , ..., -41.166893 ,\n",
       "          -41.16903  , -41.171165 ], dtype=float32),\n",
       "   'model': 'angle'}},\n",
       " {'features: ': array([[ 1.31482685, -1.        ],\n",
       "         [ 1.34382689, -1.        ],\n",
       "         [ 1.57382441, -1.        ],\n",
       "         ...,\n",
       "         [ 1.71682262, -1.        ],\n",
       "         [ 1.47482562, -1.        ],\n",
       "         [ 1.4528259 , -1.        ]]),\n",
       "  'labels': array([-1.5496522 ,  2.5096037 ,  0.22222184,  1.1238266 ,  0.43571863],\n",
       "        dtype=float32),\n",
       "  'meta': {'v': array([-1.5496522], dtype=float32),\n",
       "   'a': array([2.5096037], dtype=float32),\n",
       "   'z': array([0.22222184], dtype=float32),\n",
       "   't': array([1.1238266], dtype=float32),\n",
       "   's': 1.0,\n",
       "   'theta': array([0.43571863], dtype=float32),\n",
       "   'delta_t': 0.0010000000474974513,\n",
       "   'max_t': 20.0,\n",
       "   'n_samples': 1000,\n",
       "   'simulator': 'ddm_flexbound',\n",
       "   'boundary_fun_type': 'angle',\n",
       "   'possible_choices': [-1, 1],\n",
       "   'trajectory': array([[  -1.3942262],\n",
       "          [  -1.390434 ],\n",
       "          [  -1.4434246],\n",
       "          ...,\n",
       "          [-999.       ],\n",
       "          [-999.       ],\n",
       "          [-999.       ]], dtype=float32),\n",
       "   'boundary': array([ 2.5096037,  2.509138 ,  2.5086727, ..., -6.80068  , -6.8011456,\n",
       "          -6.801611 ], dtype=float32),\n",
       "   'model': 'angle'}},\n",
       " {'features: ': array([[1.96486604, 1.        ],\n",
       "         [1.91186666, 1.        ],\n",
       "         [1.88486707, 1.        ],\n",
       "         ...,\n",
       "         [1.74086714, 1.        ],\n",
       "         [1.64786708, 1.        ],\n",
       "         [1.78686726, 1.        ]]),\n",
       "  'labels': array([-0.1372501 ,  0.71668977,  0.7275491 ,  1.608867  ,  0.44358554],\n",
       "        dtype=float32),\n",
       "  'meta': {'v': array([-0.1372501], dtype=float32),\n",
       "   'a': array([0.71668977], dtype=float32),\n",
       "   'z': array([0.7275491], dtype=float32),\n",
       "   't': array([1.608867], dtype=float32),\n",
       "   's': 1.0,\n",
       "   'theta': array([0.44358554], dtype=float32),\n",
       "   'delta_t': 0.0010000000474974513,\n",
       "   'max_t': 20.0,\n",
       "   'n_samples': 1000,\n",
       "   'simulator': 'ddm_flexbound',\n",
       "   'boundary_fun_type': 'angle',\n",
       "   'possible_choices': [-1, 1],\n",
       "   'trajectory': array([[ 3.2616419e-01],\n",
       "          [ 3.5521433e-01],\n",
       "          [ 3.6585027e-01],\n",
       "          ...,\n",
       "          [-9.9900000e+02],\n",
       "          [-9.9900000e+02],\n",
       "          [-9.9900000e+02]], dtype=float32),\n",
       "   'boundary': array([ 0.71668977,  0.7162146 ,  0.7157394 , ..., -8.785724  ,\n",
       "          -8.786199  , -8.786674  ], dtype=float32),\n",
       "   'model': 'angle'}}]"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "training_data[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "max_n_trials = 3000\n",
    "mydict = {\n",
    "    0: {\"features\": np.zeros((max_n_trials, 2)), \"labels\": np.ones(4)},\n",
    "    1: {\"features\": np.zeros((max_n_trials, 2)), \"labels\": np.ones(4)},\n",
    "}\n",
    "\n",
    "\n",
    "n_trials = int(np.random.uniform(low=500, high=3000))\n",
    "n_batch = 2\n",
    "\n",
    "# Inside the dataloader\n",
    "my_batch = np.zeros((n_batch, n_trials, 2))\n",
    "\n",
    "for i in range(n_batch):\n",
    "    my_batch[i, :, :] = mydict[i][\"features\"][\n",
    "        np.random.choice(max_n_trials, n_trials, replace=False), :\n",
    "    ]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2, 1488, 2)"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "my_batch.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([4, 5])"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.random.choice(10, 2, replace=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`training_data` is a dictionary containing four keys:\n",
    "\n",
    "1. `data` the features for [LANs](https://elifesciences.org/articles/65074), containing vectors of *model parameters*, as well as *rts* and *choices*.\n",
    "2. `labels` which contain approximate likelihood values\n",
    "3. `generator_config`, as defined above\n",
    "4. `model_config`, as defined above"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can now use this training data for your purposes. If you want to train [LANs](https://elifesciences.org/articles/65074) yourself, you might find the [LANfactory](https://github.com/AlexanderFengler/LANfactory) package helpful.\n",
    "\n",
    "You may also simply find the basic simulators provided with the **ssms** package useful, without any desire to use the outputs into training data for amortization purposes.\n",
    "\n",
    "##### END"
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "c2404e761a8d4e2a34f63613cf4c9a9997cd3109cabb959a7904b2035989131a"
  },
  "kernelspec": {
   "display_name": "ssms_dev",
   "language": "python",
   "name": "ssms_dev"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.12"
  },
  "orig_nbformat": 2
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
